home *** CD-ROM | disk | FTP | other *** search
- /* ppmchange.c - change a given color to another
- **
- ** Copyright (C) 1991 by Wilson H. Bent, Jr.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- **
- ** Modified by Alberto Accomazzi (alberto@cfa.harvard.edu).
- ** 28 Jan 94 - Added support for multiple color substitution.
- ** Modified by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
- ** 17 Jun 94 - fixed maxval bug, rework to use hash tables, "-file" and "-other" options
- */
-
- #include "ppm.h"
- #include "ppmcmap.h"
-
- #define TCOLS 1024
-
-
- static void add_colorchange ARGS((char *name1, char *name2, pixval maxval,
- colorhash_table hashtable, pixel *changerow, int *idxP));
-
-
- int
- main( argc, argv )
- int argc;
- char* argv[];
- {
- FILE* ifp;
- int argn, format, first, last;
- register int row, col, i;
- int rows, cols, ncolors, maxcolors, changes;
- pixel *prow, *new, pix;
- colorhash_table cht;
- pixval maxval;
- char *chfile = NULL;
- char *othercol = NULL;
- char *usage = "[-file <changesfile>] [-other <color>] [<oldcolor> <newcolor> [...]] [ppmfile]";
-
- ppm_init( &argc, argv );
-
- argn = 1;
- while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
- if( pm_keymatch(argv[argn], "-file", 2) ) {
- if( ++argn >= argc ) pm_usage(usage);
- chfile = argv[argn];
- }
- else
- if( pm_keymatch(argv[argn], "-other", 2) ) {
- if( ++argn >= argc ) pm_usage(usage);
- othercol = argv[argn];
- }
- else
- pm_usage(usage);
- ++argn;
- }
-
- first = argn;
- if( argn < argc ) {
- last = argc-1;
- if( !odd(last-first) ) last--;
- argn = last+1;
- }
- ncolors = (argn-first)/2; /* (last-first+1)/2 */
-
- if( argn < argc ) {
- ifp = pm_openr(argv[argn]);
- ++argn;
- }
- else
- ifp = stdin;
- if( argn != argc )
- pm_usage(usage);
-
- ppm_pbmmaxval = PPM_MAXMAXVAL;
- ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
- ppm_writeppminit( stdout, cols, rows, maxval, 0 );
- prow = ppm_allocrow( cols );
-
- maxcolors = ncolors + TCOLS;
- cht = ppm_alloccolorhash();
- new = ppm_allocrow(maxcolors);
- changes = 0;
- if( chfile ) {
- FILE *fp;
- char buf1[256], buf2[256];
- if( fp = fopen(chfile, "r") ) {
- while( fscanf(fp, "%s %s", buf1, buf2) == 2 ) {
- if( changes == TCOLS ) {
- pm_message("too many color changes in file (max %d) - ignoring extra", TCOLS);
- break;
- }
- add_colorchange(buf1, buf2, maxval, cht, new, &changes);
- }
- fclose(fp);
- }
- else
- pm_error("cannot open changes file");
- }
- for( i = 0; i < ncolors; i++, first += 2 )
- add_colorchange(argv[first], argv[first+1], maxval, cht, new, &changes);
- if( othercol )
- pix = ppm_parsecolor(othercol, maxval);
-
- /* Scan for the desired color */
- for ( row = 0; row < rows; ++row ) {
- ppm_readppmrow( ifp, prow, cols, maxval, format );
- for ( col = 0; col < cols; ++col ) {
- i = ppm_lookupcolor(cht, &prow[col]);
- if( i >= 0 )
- prow[col] = new[i];
- /*PPM_ASSIGN(prow[col], PPM_GETR(new[i]), PPM_GETG(new[i]), PPM_GETB(new[i]));*/
- else
- if( othercol )
- prow[col] = pix;
- /*PPM_ASSIGN(prow[col], PPM_GETR(pix), PPM_GETG(pix), PPM_GETB(pix));*/
- }
- ppm_writeppmrow( stdout, prow, cols, maxval, 0 );
- }
- pm_close( ifp );
-
- exit( 0 );
- }
-
-
- static void
- add_colorchange(name1, name2, maxval, hashtable, changerow, idxP)
- char *name1, *name2;
- pixval maxval;
- colorhash_table hashtable;
- pixel *changerow;
- int *idxP;
- {
- int i;
- pixel p1, p2;
-
- p1 = ppm_parsecolor(name1, maxval);
- p2 = ppm_parsecolor(name2, maxval);
-
- i = ppm_lookupcolor(hashtable, &p1);
- if( i >= 0 )
- changerow[i] = p2;
- else {
- if( ppm_addtocolorhash(hashtable, &p1, *idxP) < 0 )
- pm_error("cannot add to color hash table - out of memory?");
- changerow[*idxP] = p2;
- (*idxP)++;
- }
- }
-
-